$setto(this,{
xmlMaster: function(){
    var m_id = -1;
    var m_pool = new Array();
    var m_loadComplete = function(xItem){
        if (!xItem){ return; }
        return $exes(xItem.CBFunc, [xItem.XmlDoc]);
        m_removeItem(m_id);
    };
    var m_removeItem = function(xId){
        if (xId >= m_pool.length){ return; }
        var xItem = m_pool[xId];
        m_pool[xId] = null;
        $dispose(xItem);
    };
    this.loadXml = function(xmlString, cb){
        var xItem = new xmlItem(++m_id, cb);
        m_pool[m_id] = xItem;
        $try(
        function(){
            xItem.XmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xItem.XmlDoc.async = false;
            xItem.XmlDoc.loadXML(xmlString);
        },
        function(){
            var dp = new DOMParser();
            xItem.XmlDoc = dp.parseFromString(xmlString,"text/xml");
        });
        var rtval = $get(xItem,"XmlDoc");
        m_loadComplete(xItem);
        return rtval;
    };
    this.load = function(url, cb, isasy){
        var othis = this;
        var rtval = null;
        var xItem = new xmlItem(++m_id, cb);
        var fcb = function(xml){
            rtval = othis.loadXml(xml, cb);
        };
        var aItem = $ajax.getResp(url, fcb, isasy, false);
        return rtval;
    };
    this.trans = function(xml, xsl, isxurl, issurl, cb){
        var xmlDoc = !!isxurl ? this.load(xml, null, false) : this.loadXml(xml);
        var xslDoc = !!issurl ? this.load(xsl, null, false) : this.loadXml(xsl);
        var rtval = null;
        $try(
        function(){ rtval = xmlDoc.transformNode(xslDoc); },
        function(){
            var xPrcs = new XSLTProcessor();
            xPrcs.importStylesheet(xslDoc);
            rtval= xPrcs.transformToDocument(xmlDoc);
            return rtval;
        });
        $exes(cb, [xmlDoc, xslDoc]);
        xmlDoc = null;
        xslDoc = null;
        return rtval;
    };
    this.transUrl = function(mul, sul, cb){
        return this.trans(mul, sul, true, true, cb);
    };
    this.transXml = function(xml, xsl, cb){
        return this.trans(xml, xml, false, false, cb);
    };
},
xmlItem: function(id, cb){
    this.Id = id;
    this.CBFunc = cb;
    this.XmlDoc = null;
    this.dispose = function(){
        this.Id = null;
        this.CBFunc = null;
        this.XmlDoc = null;
    };
}});
$setto(xmlMaster.prototype, {
fromJson: function(obj, root){
    root = String(root || "JSONTAGWRAPPER");
    var nd = "<{0}{1}>{2}{3}</{0}>".format(root, "{0}","{1}","{2}");
    if ($oArr(obj)){nd = "{0}{1}{2}";}
    for (var k in obj){
        var pnm = String(k), val = null;
        try{
            if ($oVal(obj[k])){
                val = $V(obj[k]);
            }else if (!$oFun(obj[k])){
                val = this.fromJson(obj[k], ((parseInt(k)>=0) ? root : pnm));
            }else{
                continue;
            }
        }catch(ex){
            val = "'_E/R_'";
        }
        if (pnm == "$"){
            nd = nd.format("{0}",val+"{1}","{2}");
        }else if (pnm.indexOf("$")==0){
            nd = nd.format((' {0}="{1}"'.format(pnm.substr(1), val))+"{0}","{1}","{2}");
        }else{    
            nd = nd.format("{0}","{1}",val+"{2}");
        }
    }
    return nd.format("","","");
},
toJson: function(xmlstr,igtags){
    var m_toJson = function(xmlstr,autowrap){
        if (!!autowrap) xmlstr = '<JSONTAGWRAPPER>' + xmlstr + '</JSONTAGWRAPPER>';
	    var splStr = "`~'", y=[], level=0, opentags=[];
		var x=xmlstr.replace(/<\//g,splStr).split("<");
		for (var i=1,l=x.length;i<l;i++){
			opentags.push(x[i].split(">")[0]);
			y.push((++level)+"<"+x[i].split(splStr)[0]);
			while(x[i].indexOf(splStr+opentags[opentags.length-1]+">")>=0){level--;opentags.pop()}
		};
		var oldniva=-1, xml__to__json__temp__object = {}, objname="xml__to__json__temp__object";
		for (var i=0,l=y.length;i<l;i++){
			var preeval="", niva=y[i].split("<")[0], rest=y[i].split(">")[1], tagnamn=y[i].split("<")[1].split(">")[0].toLowerCase();
			if(niva<=oldniva){
				var tabort=oldniva-niva+1;
				for (var j=0;j<tabort;j++){objname=objname.substring(0,objname.lastIndexOf("."))}
			}
			objname+="."+tagnamn;
			var pobject=objname.substring(0,objname.lastIndexOf("."));
			if (eval("typeof "+pobject) != "object"){preeval+=pobject+"={$:"+pobject+"};\n"};
			var objlast=objname.substring(objname.lastIndexOf(".")+1), already=false, onlywhites=true;
			for (k in eval(pobject)){
			    if(k==objlast){already=true}
			}
			for (var s=0,sl=rest.length;s<sl;s+=3){
				if(rest.charAt(s)!="%"){onlywhites=false;break;}
			}
			if (rest!="" && !onlywhites){
				if(rest/1!=rest){
					rest="'"+rest.replace(/\'/g,"\\'")+"'";
					rest=rest.replace(/\*\$\*\*\*/g,"</").replace(/\*\$\*\*/g,"<").replace(/\*\*\$\*/g,">");
				}
			}else{rest="{}"}
			if (rest.charAt(0)=="'"){rest='unescape('+rest+')'}
			if (already && !eval(objname+".sort")){preeval+=objname+"=["+objname+"];\n"}
			var before="=";after="";
			if (already){before=".push(";after=")"}
			eval(preeval+objname+before+rest+after);
			if(eval(objname+".sort")){objname+="["+eval(objname+".length-1")+"]"};
			oldniva=niva;
		}
		return (!!autowrap ? xml__to__json__temp__object.jsontagwrapper : xml__to__json__temp__object);
    };
    var m_attris2Tags = function(x){
        var r=[];
        r.push(new RegExp(" ","g"));
        r.push(new RegExp("=","g"));
        r.push(new RegExp('"',"g"));
        r.push(new RegExp("'","g"));
        
	    x = x.replace(/\s*\/>/g,'/>').replace(/<\?[^>]*>/g,"").replace(/<\![^>]*>/g,"");
	    x = x.split("/>");
	    for (var i=1,l=x.length;i<l;i++){
		    var t=x[i-1].substring(x[i-1].lastIndexOf("<")+1).split(" ")[0];
		    x[i]="></"+t+">"+x[i]
	    }
	    x = x.join("").split(">");
	    var y = [];
	    for (var i=0,l=x.length;i<l;i++){
		    var temp=x[i].split("<");
		    temp[0] = parse_temp_chars(temp[0], r);
		    if (temp[0] != ""){ temp[0] = "<$>" + temp[0] + "</$>" }
		    if(temp[1]){
			    temp[1]=temp[1].replace(/'/g,'"');
			    temp[1]=temp[1].split('"');
			    for (var j=1,jl=temp[1].length;j<jl;j+=2){
    			    temp[1][j] = parse_temp_chars(temp[1][j], r);
			    };
			    temp[1]=temp[1].join('"')
		    };
		    y.push(temp.join("<"));
	    };
	    var rtval = y.join(">"), d=' ="\''.split("");
	    rtval=rtval.replace(/\s+([^=]*)=([^ |>]*)/g,"><$$$1>$2</$$$1").replace(/>"/g,">").replace(/"</g,"<");    	
	    for (var r=0;r<4;r++){rtval=rtval.replace(new RegExp("_jsonconvtemp"+r+"_","g"),d[r])}
    	rtval = escape(rtval).split("%3C").join("<").split("%3E").join(">").split("%3D").join("=").split("%22").join("\"").split("%24").join("$");
	    return rtval;
    };
    var parse_temp_chars = function(s, rs){
        var rtval = String(s);
        if (s && rs){
	        for (var i=0,l=rs.length;i<l;i++){
	            rtval=rtval.replace(rs[i], "_jsonconvtemp"+i+"_");
	        }
	    }
        return rtval;
    };
	igtags = $A(igtags);
	var x = m_attris2Tags(xmlstr);
	for (var i=0,l=igtags.length;i<l;i++){
		x = x.replace(new RegExp("<"+igtags[i]+">","g"),"*$**"+igtags[i]+"**$*");
		x = x.replace(new RegExp("</"+igtags[i]+">","g"),"*$***"+igtags[i]+"**$*");
	}
	return m_toJson(x, true);
}});
$setto(this,{$xml:new xmlMaster()});